//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2003-2007
// ALAN and ALAN Map 500 are registered trademarks of ALAN Group.
//
// ALAN Map 500 TLG (legacy) tracks export.
//

# include "StdAfx.h"
# include "HoluxTlg.h"
# include "Save.h"
# include "Map.h"
# include "Status.h"
# include "SaveFileDlg.h"
# include "FileWriter.h"
# include "fast_floor.h"
# include "Options.h"
# include "Globals.h"

class CAlanTlgExport : public CMapSaver {
  public:
	virtual bool CanSave (const map_t & _map) {return true;}
	virtual bool Save (HANDLE _hFile, const char * _strFileName, const map_t & _map);

  private:
	bool _Save (HANDLE _hFile, const map_t & _map);
};

//DECLARE_WPTRK_EXPORT (CAlanTlgExport, "alan-tlg", "tlg", "ALAN Map 500 legacy tracks (*.tlg)");

bool CAlanTlgExport::Save (HANDLE _hFile, const char * _strFileName, const map_t & _map) {
	if (_hFile) {
		return _Save (_hFile, _map);
	} else {
		//
		// Prepare file name.
		//
		char strFileName [MAX_PATH + 1];
		::strncpy (strFileName, _strFileName, MAX_PATH);
		strFileName [MAX_PATH] = '\0';
		if (! SaveFileDlg ("tlg", "ALAN Map 500 tracks (*.tlg)\0*.tlg\0", strFileName))
			return false;

		//
		// Open the file.
		//
		const CFileForWrite hFile (strFileName);
		if (! hFile.IsValid ()) {
			ErrorMsgBox ("Can't create file:\n %s", strFileName);
			return false;
		}

		return _Save (hFile, _map);
	}
}

bool CAlanTlgExport::_Save (HANDLE _hFile, const map_t & _map) {
	BYTE baData [0x20000];
	::memset (baData, 0, sizeof (baData));
	CTlgTrackLog * const pLogs [c_cTlgMaxTracks] = {
		reinterpret_cast<CTlgTrackLog *> (baData),
		reinterpret_cast<CTlgTrackLog *> (baData + sizeof (CTlgTrackLog)),
		reinterpret_cast<CTlgTrackLog *> (baData + sizeof (CTlgTrackLog)*2),
		reinterpret_cast<CTlgTrackLog *> (baData + 0x10000),
		reinterpret_cast<CTlgTrackLog *> (baData + 0x10000 + sizeof (CTlgTrackLog)),
	};

	CTlgHdr hdr;
	::memset (& hdr, 0, sizeof (hdr));
	hdr.dwSignature = c_dwTlgSignature;

	//
	// Write the file.
	//
	SetProgressStatus (0);

	size_t cOrdinal = 0;
	bool bLostPoints = false;

	size_t cRgn = 0;
	const size_t cRgns = _map.GetRgnCount ();
	for (size_t cKind = 0; cKind < rkMax; ++ cKind) {
		const layer_t & layer = _map.layers [cKind];
		const rgns_t & rgns = layer.rgns;
		for (rgns_t::const_iterator iRgn = rgns.begin (); iRgn != rgns.end (); ++ iRgn, ++ cRgn) {
			const rgn_t & rgn = * iRgn;
			if (rgn.IsDeleted () || ! rgn.IsTrack ())
				continue;

			// Save track.
			for (size_t cElement = 0; cElement < rgn.elements.size (); ++ cElement) {
				const rgn_element_t & element = rgn.elements [cElement];
				if (element.bDeleted)
					continue;
				const points_t & points = element.points;
				const size_t cPoints = points.size ();
				if (cPoints == 0)
					continue;

				if (cOrdinal >= c_cTlgMaxTracks)
					break;

				CTlgTrackLog & log = * (pLogs [cOrdinal]);
				for (size_t cPoint = 0; cPoint < cPoints; ++ cPoint) {
					if (cPoint >= c_cTlgMaxPoints) {
						bLostPoints = true;
						break;
					}

					CTlgPoint & pt = log.points [cPoint];
					const point_t & point = points [cPoint];
					pt.lX =  fast_floor (point.x*36000 + .5f);
					pt.lY = -fast_floor (point.y*36000 + .5f);
				}

				CTlgTrack & track = hdr.tracks [cOrdinal];

				track.wPoints = cPoints;
				track.wNextPoint = cPoints;

				// Name.
				::strncpy (track.strName, rgn.strLabel.c_str (), sizeof (track.strName));
				track.strName [sizeof (track.strName) - 1] = '\0';

				// Comment.
				::memset (& track.strComment, ' ', sizeof (track.strComment));
				::strncpy (track.strComment, rgn.strComment.c_str (), rgn.strComment.size () < sizeof (track.strComment) ? rgn.strComment.size () : sizeof (track.strComment));

				track.dwOccupied = 1;
				track.dwShow = 1;
				track.dwFill = 0;

				++ cOrdinal;
			}

			SetProgressStatus (fast_floor (100.f*cRgn/cRgns + .5f));
		}
	}
	hdr.wTracks = cOrdinal;

	if (cOrdinal >= c_cTlgMaxTracks)
		WarningMsgBox ("Only first 5 tracks are saved.\n(NOTE:this is the TLG format limitation).");
	if (bLostPoints)
		WarningMsgBox ("Just 2500 points per track are saved.\n(NOTE:this is the TLG format limitation).");

	CFileWriter fw (_hFile);
	fw.WriteBin (baData);
	fw.WriteBin (hdr);

	fw.FlushBuffer ();

	SetProgressStatus (100);

	return true;
}
